package com.ncmmall.application.util;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.feijin.commons.lang.PropertiesHelps;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * 支付宝支付
 *
 * @author likaikai
 * @date 2021-1-5 13:54:38
 */
@Slf4j
public class AlipayUtil {

    static {
        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = "openapi.alipay.com";
        config.signType = "RSA2";
        config.appId = PropertiesHelps.getValue("alipay.appid");
        config.merchantPrivateKey = PropertiesHelps.getValue("alipay.merchantPrivateKey");
        config.alipayPublicKey = PropertiesHelps.getValue("alipay.alipayPublicKey");
        Factory.setOptions(config);
    }

    /**
     * 创建app支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额，字符串，单位元，精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付字符串
     * @throws Exception 创建订单异常
     */
    public static String createAppOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.App().asyncNotify(notifyUrl).pay(subject, outTradeNo, String.valueOf(totalAmount)).getBody();
    }

    /**
     * 创建PC支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额，字符串，单位元，精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付字符串
     * @throws Exception 创建订单异常
     */
    public static String createPageOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.Page().asyncNotify(notifyUrl).pay(subject, outTradeNo, String.valueOf(totalAmount), "").getBody();
    }

    /**
     * 创建PC二维码支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额，字符串，单位元，精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付二维码链接
     * @throws Exception 创建订单异常
     */
    public static String createPageCodeOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.FaceToFace().asyncNotify(notifyUrl).preCreate(subject, outTradeNo, String.valueOf(totalAmount)).getQrCode();
    }

    /**
     * 创建手机浏览器支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额，字符串，单位元，精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付字符串
     * @throws Exception 创建订单异常
     */
    public static String createWapOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.Wap().asyncNotify(notifyUrl).pay(subject, outTradeNo, String.valueOf(totalAmount), "", "").getBody();
    }

    /**
     * 订单申请退款
     *
     * @param outTradeNo   订单编号
     * @param refundAmount 退款金额，字符串，单位元，精确到小数2位
     * @throws Exception 退款异常
     */
    public static void refund(String outTradeNo, double refundAmount) throws Exception {
        try {
            AlipayTradeRefundResponse refund = Factory.Payment.Common().refund(outTradeNo, String.valueOf(refundAmount));
            if (!"10000".equals(refund.getCode())) {
                throw new IllegalArgumentException(refund.getSubMsg());
            }
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            log.error("支付宝退款异常", e);
            throw e;
        }
    }

    /**
     * 查询订单支付状态
     *
     * @param outTradeNo 订单号
     * @throws Exception 查询异常
     */
    public static boolean tradeQuery(String outTradeNo) throws Exception {
        String status = Factory.Payment.Common().query(outTradeNo).getTradeStatus();
        return "TRADE_SUCCESS".equals(status) || "TRADE_FINISHED".equals(status);
    }

    /**
     * 异步通知校验
     *
     * @param parameters 响应参数
     * @throws Exception 校验异常
     */
    public static boolean verifyNotify(Map<String, String> parameters) throws Exception {
        return Factory.Payment.Common().verifyNotify(parameters);
    }

}
